/*
* @Author: 窦子滨<zibin_5257@163.com>
* @Date: 2019-05-06 9:52
 */
package main

import (
	"errors"
	"github.com/lanfengye2008/hprose-golang/rpc"
	//_ "net/http/pprof"
	"reflect"
	"strings"
	"sync"
)

func main() {
	var waitGroup = new(sync.WaitGroup)

	//go func() {
	//	http.ListenAndServe("0.0.0.0:8080", nil)
	//}()


	log.Info("微服务网关启动")
	waitGroup.Add(1)
	go server(waitGroup)
	waitGroup.Add(1)
	go rpcServer(waitGroup)

	waitGroup.Wait()

	log.Error("微服务网关启动失败")
}

//转发服务器
func server(waitGroup *sync.WaitGroup) {
	service := rpc.NewTCPServer("tcp://0.0.0.0:" + Config.Server.Port)
	defer service.Close()
	defer waitGroup.Done()
	service.AddMissingMethod(proxy, rpc.Options{Mode: rpc.Raw})
	log.Info("TCP服务监听端口：" + Config.Server.Port)
	err := service.Start()

	//log.Debug("%s", err.Error())

	if err != nil {
		log.Error("打开socket TCP端口出错：" + err.Error())
		return
	}
}

func proxy(name string, args []reflect.Value, context rpc.Context) ([]reflect.Value, error) {
	log.Info("=========================================")
	log.Info("网关处理开始：[%s]", name)
	var (
		microName, method string
		service           Service
		conn              Conn
		err               error
	)
	//微服务名称
	microName = GetMicroName(name)
	//调用方法名称
	method, err = Mapping.Handle(name)
	if err != nil {
		log.Error("微服务调用名称错误：[err:%s][%s]", err, name)
		return nil, err
	}
	var uri string

	if Config.Manual.Switch {
		uri, err = manualList.DoBalance(microName)
		if err != nil {
			log.Debug("获取手动配置的微服务错误信息：[%s]", err.Error())
		}
		log.Debug("手动配置的微服务连接：[%s]", uri)
	}

	if err != nil && uri == "" && Config.Etcd.Switch {
		//自动发现
		info := autoService.RandomByName(microName)
		log.Debug("服务发现随机获取的服务：[%+v]", info)
		if info == nil {
			return nil, errors.New("微服务不存在")
		} else {
			uri = info.Uri
		}
	}

	if uri == "" {
		return nil, errors.New("微服务不存在")
	}

	log.Info("微服务转发开始：[%s][%s]", microName, method)
	service = services.NewAndGet(microName)
	conn = service.NewAndGet(uri)

	return conn.Client().Invoke(method, args, service.InvokeSettings())
}

func GetMicroName(name string) (val string) {
	s := strings.Split(name, "_")
	val = strings.ToLower(s[0])
	return
}
